#include "mainwindow.h"

#include <QBrush>
#include <QPainter>
#include <QPen>

#include "ui_mainwindow.h"

MainWindow::MainWindow( QWidget* parent )
    : QMainWindow( parent ),
      ui( new Ui::MainWindow ),
      maze( 11, 11 ),
      agent( maze )
{
    ui->setupUi( this );

    timer.setInterval( 1000 );
    connect( &timer, &QTimer::timeout, this, &MainWindow::updateAgent );
    timer.start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent( QPaintEvent* event )
{
    Q_UNUSED( event );
    QPainter painter( this );

    int cellSize = 40;
    int w        = maze.getWidth();
    int h        = maze.getHeight();

    QPen pen( Qt::black );
    painter.setPen( pen );

    for ( int i = 0; i < w; ++i )
    {
        for ( int j = 0; j < h; ++j )
        {
            if ( maze.isWall( i, j ) )
            {
                QBrush brush( Qt::gray );
                painter.fillRect( i * cellSize, j * cellSize, cellSize, cellSize, brush );
            }
        }
    }

    if ( maze.isExit( agent.getX(), agent.getY() ) )
    {
        QBrush brush( Qt::green );
        painter.fillRect( agent.getX() * cellSize, agent.getY() * cellSize, cellSize, cellSize, brush );
    }

    QBrush agentbrush( Qt::red );
    painter.fillRect( agent.getX() * cellSize, agent.getY() * cellSize, cellSize, cellSize, agentbrush );

    QPen pathPen( Qt::blue );
    painter.setPen( pathPen );
    for ( int i = 1; i < explorationPath.size(); ++i )
    {
        QPoint start = explorationPath[i - 1];
        QPoint end   = explorationPath[i];
        painter.drawLine(
            start.x() * cellSize + cellSize / 2, start.y() * cellSize + cellSize / 2, end.x() * cellSize + cellSize / 2,
            end.y() * cellSize + cellSize / 2 );
    }
}

void MainWindow::updateAgent()
{
    int action = agent.chooseAction( agent.getX(), agent.getY() );
    int oldx   = agent.getX();
    int oldy   = agent.getY();
    agent.move( action );
    explorationPath.append( QPoint( oldx, oldy ) );

    double reward = maze.isExit( agent.getX(), agent.getY() )   ? 100
                    : maze.isWall( agent.getX(), agent.getY() ) ? -10
                                                                : -1;
    agent.updateQValue( oldx, oldy, action, agent.getX(), agent.getY(), reward );
    agent.decayExplorationRate( 0.99 );
    if ( maze.isExit( agent.getX(), agent.getY() ) )
    {
        timer.stop();
    }
    update();
}
